package com.iussoft.receiveData.controller;

import com.alibaba.fastjson.JSON;
import com.apache.api.vo.ResultMsg;
import com.apache.cache.util.Validator;
import com.apache.tools.StrUtil;
import com.iussoft.es.entity.Field;
import com.iussoft.es.entity.Page;
import com.iussoft.model.DataParams;
import com.iussoft.receiveData.redis.EsManager;
import com.iussoft.receiveData.redis.SearchEsServiceImpl;
import com.iussoft.receiveData.schedul.LogWritRunable;
import com.iussoft.receiveData.schedul.ScheduledDynamicTask;
import net.sf.json.JSONObject;
import org.apache.commons.io.IOUtils;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @description: ES查询
 * @author: Hou Dayu
 * @date: Created in 2020/5/6
 */
@Controller
public class SearchEsAction {

    @Autowired
    @Qualifier("searchEsService")
    private SearchEsServiceImpl searchEsService;

    @Autowired
    private EsManager esManager;

    @Autowired
    @Qualifier("scheduledDynamicTask")
    private ScheduledDynamicTask dynamicTask;

    /**
     * @param params
     */
    @RequestMapping(value = "/searchPageList", method = RequestMethod.POST)
    @ResponseBody
    public JSONObject searchPageList(HttpServletRequest request, @RequestBody DataParams params) {
        JSONObject data = new JSONObject();
        String indexName=params.getIndexName();
        String dataType = params.getIndexType();//数据类型；log:日志; other:其他
        int pageIndex= Integer.parseInt(Validator.getDefaultStr(String.valueOf(params.getPageNo()),"0"));
        int pageSize=Integer.parseInt(Validator.getDefaultStr(String.valueOf(params.getPageAcount()),"0"));
        Map<String, Object> paramsMap = params.getParams();
        List<Map<String,Object>> fieldsList = (List<Map<String,Object>>)paramsMap.get("fields");
        List<Field> fields = new ArrayList<>();
        Field field =null;
        if(!Validator.isEmpty(fieldsList)&&fieldsList.size()>0){
            for (Map<String,Object> map:fieldsList) {
                field =new Field();
                if(Validator.isNotNull(String.valueOf(map.get("fileName")))){
                    field.setFileName(String.valueOf(map.get("fileName")));
                }else {
                    continue;
                }
                String lte =String.valueOf(map.get("lte"));
                String gte =String.valueOf(map.get("gte"));
                String from =String.valueOf(map.get("from"));
                String to =String.valueOf(map.get("to"));
                if(Validator.isNotNull(lte) || Validator.isNotNull(gte)){
                    if(Validator.isNotNull(lte)){
                        field.setLte(Long.parseLong(lte));
                    }
                    if(Validator.isNotNull(gte)){
                        field.setGte(Long.parseLong(gte));
                    }
                } else if("wildcard".equals(String.valueOf(map.get("searchType")))){
                    field.setWildcardValue(String.valueOf(map.get("fileValue")));
                }else if("term".equals(String.valueOf(map.get("searchType")))){
                    field.setFileValue(String.valueOf(map.get("fileValue")));
                }else if(Validator.isNotNull(from) || Validator.isNotNull(gte)){
                    if(Validator.isNotNull(from)){
                        field.setFrom(from);
                    }
                    if(Validator.isNotNull(to)){
                        field.setTo(to);
                    }
                }
                field.setSearchType(String.valueOf(map.get("searchType")));
                fields.add(field);
            }
        }
        //暂时不支持
        List<Map<String,Object>> fieldForOrsList = (List<Map<String,Object>>)paramsMap.get("fieldForOrs");
        List<Field> fieldForOrs = null;
        if(!Validator.isEmpty(fieldForOrsList)&&fieldForOrsList.size()>0){
            fieldForOrs = new ArrayList<>();
            for (Map<String,Object> map:fieldForOrsList) {
                field =new Field();
                field.setFileName(String.valueOf(map.get("fileName")));
                field.setWildcardValue(String.valueOf(map.get("fileValue")));
                field.setSearchType(String.valueOf(map.get("searchType")));
                fieldForOrs.add(field);
            }
        }
        //暂时不支持
        String dataStatus="";

        SortBuilder sortBuilder = null;
        if(StrUtil.isNotNull(params.getOrderCloumn())){
            sortBuilder = SortBuilders.fieldSort(params.getOrderCloumn());
            if ("asc".equalsIgnoreCase(params.getOrderSort())) {
                sortBuilder.order(SortOrder.ASC);
            } else {
                sortBuilder.order(SortOrder.DESC);
            }
        }
        Page pageList = searchEsService.pageList(indexName, dataType, pageIndex, pageSize, fields, fieldForOrs, dataStatus, sortBuilder);
        if("0".equals(String.valueOf(pageList.getErrorCode()))){
            /*List rows = new ArrayList();
            if(!Validator.isEmpty(pageList.getPageObjects())){
                rows=pageList.getPageObjects();
            }*/
            data.put("flag","T");
            data.put("total",pageList.getCount());
            data.put("rows",pageList.getPageObjects()==null?new ArrayList<>():pageList.getPageObjects());
            data.put("msg","查询成功");
        } else {
            data.put("flag","F");
            data.put("msg",pageList.getMessage());
        }
        return data;
    }

    /**
     * 按条件删除ES doc
     * @param params
     */
    @RequestMapping(value = "/delByQuery/{indexName}", method = {RequestMethod.POST,RequestMethod.GET})
    @ResponseBody
    public JSONObject delByQuery(HttpServletRequest request, @PathVariable("indexName") String indexName, @RequestBody Map<String,Object> params) {
        JSONObject data = new JSONObject();
        List<Field> fields = new ArrayList();
        Field field =null;
        for(String fileName : params.keySet()){
            Map<String,String> map = (Map)params.get(fileName);
            field = new Field();
            field.setFileName(fileName);
            String lte = map.get("lte");
            String gte = map.get("gte");
            String from = map.get("from");
            String to = map.get("to");
            if(Validator.isNotNull(lte) || Validator.isNotNull(gte)){
                if(Validator.isNotNull(lte)){
                    field.setLte(Long.parseLong(lte));
                }
                if(Validator.isNotNull(gte)){
                    field.setGte(Long.parseLong(gte));
                }
            } else if("wildcard".equals(map.get("searchType"))){
                field.setWildcardValue(map.get("fileValue"));
            } else if(Validator.isNotNull(from) || Validator.isNotNull(gte)){
                if(Validator.isNotNull(from)){
                    field.setFrom(from);
                }
                if(Validator.isNotNull(to)){
                    field.setTo(to);
                }
            } else {
                field.setFileValue(map.get("fileValue"));
            }
            field.setSearchType(StrUtil.doNull(map.get("searchType"),"term"));
            fields.add(field);
        }

        if(fields==null && fields.size()==0){
            data.put("flag","F");
            data.put("msg","删除条件不能为空");
            return data;
        }
       boolean mark = esManager.delDocByQuery(indexName,fields);
        if(mark){
            data.put("flag","T");
            data.put("msg","删除成功");
        } else {
            data.put("flag","F");
            data.put("msg","删除失败");
        }
        return data;
    }

    /**
     * 写日志
     */
    @RequestMapping(value = "/write/{indexName}", method = RequestMethod.POST)
    @ResponseBody
    public Object writeLogs(HttpServletRequest request, @PathVariable("indexName") String indexName){
        String logMessage = request.getHeader("logMessage");
        String levelStr = request.getParameter("levelStr");
        if(StrUtil.isNotNull(logMessage) && StrUtil.isNotNull(indexName)){
            try {
                logMessage = URLDecoder.decode(logMessage, "UTF-8");
                LogWritRunable runable = new LogWritRunable(logMessage,levelStr,indexName);
                dynamicTask.submit(runable);
            } catch (UnsupportedEncodingException e) {
            }
        }
        return new ResultMsg("T","写入完成");
    }

    /**
     * 基本统计
     */
    @RequestMapping(value = "/statisticsByQuery/{indexName}", method = {RequestMethod.POST,RequestMethod.GET})
    @ResponseBody
    public JSONObject statisticsByQuery(HttpServletRequest request, @PathVariable("indexName") String indexName) {
        JSONObject data = new JSONObject();
        data.put("flag","F");
        data.put("msg","获取失败");
        try {
            String reqMsg = IOUtils.toString(request.getInputStream(),"UTF-8");
            if(StrUtil.isNull(reqMsg)) {
                String date_histogram = StrUtil.doNull(request.getParameter("dateHistogram"), "{\"field\": \"indexDate\",\"interval\": \"1h\",\"time_zone\": \"Asia/Shanghai\",\"min_doc_count\": 1 }");
                String aggs = request.getParameter("aggs");
                String match_phrase = StrUtil.doNull(request.getParameter("matchPhrase"), "");
                String gte = request.getParameter("gte");
                String lte = StrUtil.doNull(request.getParameter("lte"), System.currentTimeMillis() + "");
                String timeName = StrUtil.doNull(request.getParameter("timeName"), "@timestamp");
                reqMsg = queryStr(date_histogram, aggs, match_phrase, gte, lte, timeName);
            }
            String indexType =StrUtil.doNull(request.getParameter("indexType"),"log");
            JSONObject query = JSONObject.fromObject(reqMsg);
            Object obj = searchEsService.searchByQuery(indexName,indexType, query);
            if(null != obj){
                data.put("flag","T");
                data.put("msg","获取成功");
                data.put("data",JSON.toJSONString(obj));
            } else {
                data.put("msg","暂无数据");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return data;
    }

    /**
     * ES查询
     */
    @RequestMapping(value = "/searchPageList/{indexName}/{indexType}", method = RequestMethod.POST)
    @ResponseBody
    public JSONObject searchPageList(HttpServletRequest request, @PathVariable("indexName") String indexName, @PathVariable("indexType") String indexType) {
        JSONObject data = new JSONObject();
        data.put("flag","F");
        data.put("msg","获取失败");
        try {
            String queryStr = IOUtils.toString(request.getInputStream(),"UTF-8");
            if(StrUtil.isNull(queryStr)){
                data.put("msg","缺少查询条件");
            }else {
                Map<String,Object> list = searchEsService.pageList(indexName, indexType, queryStr);
                if(StrUtil.isEmpty(list)){
                    data.put("msg","暂无数据");
                } else {
                    data.put("flag","T");
                    data.put("msg","获取成功");
                    data.putAll(list);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return data;
    }


    private String queryStr(String date_histogram,String aggs,String match_phrase,String gte,String lte,String timeName){
        StringBuilder sb = new StringBuilder();
        sb.append("{\"size\": 0,  \"_source\": {  \"excludes\": [] },  \"aggs\": {   \"2\": {");
        sb.append("      \"date_histogram\": "+date_histogram);//{"field": "indexDate","interval": "1h","time_zone": "Asia/Shanghai","min_doc_count": 1 }
        if(StrUtil.isNotNull(aggs)) {
            sb.append(",        \"aggs\": " + aggs);//{"1": {"max": {"field": "total"}}}
        }
        String timeNamestr = "\"@timestamp\"";
        if(StrUtil.isNotNull(timeName)){
            timeNamestr = "\""+timeName+"\"";
        }
        sb.append("}  },\n" +
                "  \"stored_fields\": [\"*\"]," +
                "  \"script_fields\": {}," +
                "  \"docvalue_fields\": ["+timeNamestr+"]," +
                "  \"query\": { \"bool\": {" +
                "      \"must\": [ {\"match_all\": {}},");
        if(StrUtil.isNotNull(match_phrase)) {
            sb.append("{\"match_phrase\": " + match_phrase+"},");// { "match_phrase": {   "infoType": {   "query": "info" }}},
        }
        sb.append("       {\"range\": {\""+timeName+"\": {");
        if(StrUtil.isNull(gte)){
            Date date = new Date();
            date.setHours(date.getHours () - 2);
            gte = date.getTime()+"";
        }
        sb.append("              \"gte\": "+gte+"," );
        sb.append("              \"lte\": "+lte+"," +
                "              \"format\": \"epoch_millis\"" +
                "            }" +
                "          }" +
                "        }" +
                "      ]," +
                "      \"filter\": []," +
                "      \"should\": []," +
                "      \"must_not\": []" +
                "    }" +
                "  }" +
                "}");
        return sb.toString();
    }
}
